package com.xinyue.network.codec;

import com.alibaba.fastjson.JSON;
import com.xinyue.network.hamdlermapping.MessageClassKey;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author 王广帅
 * @Date 2021/1/24 17:40
 */
public class GameCodecFactory {

    private static Map<MessageClassKey, Class<? extends IGameMessage>> messageClassMap = new HashMap<>();

    public static MessageClassKey addMessageClass(Class<? extends IGameMessage> clazz) {
        GameMessageMeta gameMessageMeta = clazz.getAnnotation(GameMessageMeta.class);
        MessageClassKey messageClassKey = new MessageClassKey(gameMessageMeta.messageId(), gameMessageMeta.messageType());
        messageClassMap.put(messageClassKey, clazz);
        return messageClassKey;
    }

    public static ByteBuf writeMessage(GameMessageContext gameMessageContext) {
        IGameMessage gameMessage = gameMessageContext.getGameMessage();
        int totalSize = 4;//消息长度所占字节数量
        byte[] bodyBytes = null;
        if (gameMessage != null) {
            String toJson = JSON.toJSONString(gameMessage);
            bodyBytes = toJson.getBytes(StandardCharsets.UTF_8);
            totalSize += bodyBytes.length;
        }
        GameMessageHeader header = gameMessageContext.getHeader();
        totalSize += header.HEADER_LENGTH;

        ByteBuf byteBuf = ByteBufAllocator.DEFAULT.directBuffer(totalSize);
        byteBuf.writeInt(totalSize);
        //写入包头信息
        header.write(byteBuf);
        //写入包体信息
        if (bodyBytes != null && bodyBytes.length > 0) {
            byteBuf.writeBytes(bodyBytes);
        }
        return byteBuf;
    }

    public static GameMessageContext readMessage(ByteBuf byteBuf) {
        int messageSize = byteBuf.readInt();
        GameMessageHeader header = new GameMessageHeader();
        header.read(byteBuf);
        IGameMessage gameMessage = null;
        if (byteBuf.isReadable()) {
            byte[] body = new byte[byteBuf.readableBytes()];
            byteBuf.readBytes(body);
            int messageId = header.getMessageId();
            MessageClassKey classKey = new MessageClassKey(messageId, header.getMessageType());
            Class<? extends IGameMessage> clazz = messageClassMap.get(classKey);
            if (clazz == null) {
                throw new IllegalArgumentException("不存在的消息:" + messageId);
            }
            String toJson = new String(body, StandardCharsets.UTF_8);
            gameMessage = JSON.parseObject(toJson, clazz);
        }
        GameMessageContext gameMessageContext = new GameMessageContext(header);
        gameMessageContext.setGameMessage(gameMessage);
        return gameMessageContext;
    }
}
